Widget Block (Sidebar/Footer)
Widget Block là mô hình widget cũ, chủ yếu dành cho các khu vực Sidebar, Footer truyền thống. Nếu bạn muốn sử dụng cho Page Builder, hãy xem tài liệu Tạo Widget Element.
1. Tổng Quan Kiến Trúc Widget Block
1.1 Khác biệt giữa Widget Block và Widget Element
| Tính chất | Widget Block (Sidebar) | Widget Element (Builder) |
|---|---|---|
| Class Kế thừa | SkillDo\Cms\Widget\Widget | SkillDo\Cms\Element\Element |
| Vị trí widget.json | "widgets" -> "block" | "elements" -> "general" / "header" |
| Render Tiêu đề | Có tham số cấu hình riêng (Heading options) | Thường tích hợp sẵn trong config |
| Tự động áp dụng | Không bắt buộc có icon() | |
| Mục đích chính | Dùng cho Sidebar (dọc), Footer truyền thống | Kéo thả trong giao diện Home/Page Builder |
1.2 Hệ thống phân cấp Class
2. Cấu Trúc Thư Mục
Thư mục chuẩn cho Widget Blocks nằm tại views/theme-store/widget/blocks/. Bạn nên chia vào các thư mục theo chức năng (như about, posts, products,...). Tại đây, ta lấy ví dụ một danh mục block tên là demo_block.
views/theme-store/widget/blocks/demo-block/style1/
├── demo_block_style_1.widget.php # Class chính (extends Widget)
├── views/
│ └── view.blade.php # Template hiển thị
└── assets/ # (Tùy chọn) CSS/LESS/JS
├── style-1.less
└── style-1.js
3. Tạo Widget Block Cơ Bản (Step-by-step)
Bước 1: Tạo file Widget Class
Tạo file views/theme-store/widget/blocks/demo-block/style1/demo_block_style_1.widget.php:
<?php
use SkillDo\Cms\Widget\Widget;
use SkillDo\Cms\Support\Theme;
use Theme\Supports\ThemeWidget;
class widget_demo_block_style_1 extends Widget
{
function __construct()
{
// Tham số 1: Tên Class (key hệ thống)
// Tham số 2: Tên hiển thị mặc định
parent::__construct('widget_demo_block_style_1', 'Demo Block (Style 1)');
// Thêm tag để d ễ gom nhóm / quản lý (không bắt buộc)
$this->setTags('demo');
// Tải các tài nguyên CSS / JS riêng lẻ
$this->assets('assets/style-1.less');
// $this->assets('assets/style-1.js');
}
/**
* Khai báo form cấu hình trong màn hình Add/Edit Widget
*/
public function form(): void
{
// 1. Thêm Fields vào Tab "Nội dung" (generate)
$this->tabs('generate')->adds(function (\SkillDo\Cms\Form\Form $form)
{
$form->number('limit', ['label'=> 'Số item', 'start' => 6, 'value' => 5]);
$form->wysiwyg('description', ['label' => 'Mô tả']);
});
// 2. Thêm Fields vào Tab "Kiểu dáng" (style)
$this->tabs('style')->adds(function (\SkillDo\Cms\Form\Form $form)
{
$form->addGroup(function (\SkillDo\Cms\Form\Form $form)
{
$form->boxBuilding('boxStyle', [
'label' => 'Khung bên ngoài',
'customInput' => ['colorHover' => true]
])->popup(false);
}, $this->groupFormBox('Khung Block', 'boxStyleGroup', true));
});
parent::form();
}
/**
* Render HTML giao diện người dùng
*/
public function widget(): void
{
// Render thẻ Heading mặc định của Sidebar Widget
// Function ThemeWidget::heading sẽ lấy config tiêu đề từ $this->options->heading
$header = ThemeWidget::heading($this->name, $this->options->heading ?? [], '.js_'.$this->key.'_'.$this->id);
Theme::view($this->getDir().'views/view', [
'id' => $this->id,
'name' => $this->name,
'options' => $this->options,
'header' => $header,
]);
}
/**
* Trả về file CSS động
*/
public function cssBuilder(): string
{
// Sử dụng cssSelector (Hỗ trợ responsive và trạng thái hover/active cực tốt)
$this->cssSelector('.demo-block-wrapper', [
'data' => $this->options->boxStyle ?? [],
'style' => 'box',
]);
return $this->cssBuild();
}
/**
* Gán giá trị mặc định lúc mới khởi tạo block
*/
public function default(): void
{
// Nếu tên vẫn là mặc định, có thể đổi sang tên thân thiện hơn
if($this->name == 'Demo Block (Style 1)') {
$this->name = 'Danh sách Demo';
}
$this->options->heading = $this->options->heading ?? [];
$this->options->limit = $this->options->limit ?? 5;
}
}
Bước 2: Tạo View Template
Tạo file views/theme-store/widget/blocks/demo-block/style1/views/view.blade.php:
<div class="demo-block-wrapper js_{{ $key ?? '' }}_{{ $id }}">
{{-- Hiển thị thẻ Tiêu Đề Widget --}}
{!! $header !!}
<div class="demo-content">
@if(!empty($options->description))
<div class="description">{!! $options->description !!}</div>
@endif
<p>Số lượng item cần hiển thị: {{ $options->limit }}</p>
</div>
</div>